package com.googlecode.publicholiday.service;

import com.googlecode.publicholiday.repository.ImmutablePublicHolidayRepository;
import org.joda.time.LocalDate;

import static com.googlecode.publicholiday.utils.Validation.notBlank;
import static org.apache.commons.lang.Validate.notNull;

public class DefaultWorkingDayService implements WorkingDayService {

    private final ImmutablePublicHolidayRepository publicHolidayRepository;
    private final boolean[] workingDays;

    public DefaultWorkingDayService(ImmutablePublicHolidayRepository publicHolidayRepository) {
        this(publicHolidayRepository, new boolean[] {true, true, true, true, true, false, false});
    }

    public DefaultWorkingDayService(ImmutablePublicHolidayRepository publicHolidayRepository, boolean[] workingDays) {
        this.publicHolidayRepository = publicHolidayRepository;
        this.workingDays = workingDays;
    }

    @Override
    public LocalDate addWorkingDays(String countryCode, LocalDate date, int offset) {
        notBlank(countryCode, "Country Code cannot be null or a blank String");
        notNull(date, "Date must not be null");

        LocalDate newDate = new LocalDate(date);

        int direction = Integer.signum(offset);
        if (direction == 0) {
            direction = 1;
        }

        int delta = (offset * direction) + 1;
        while (delta > 0) {
            if (isWorkingDay(countryCode, newDate)) {
                --delta;
            }
            newDate = newDate.plusDays(direction);
        }
        return newDate.plusDays(-direction);
    }

    @Override
    public LocalDate nextWorkingDay(String countryCode, LocalDate date) {
        return addWorkingDays(countryCode, date, isWorkingDay(countryCode, date) ? 1 : 0);
    }

    @Override
    public boolean isWorkingDay(String countryCode, LocalDate date) {
        return isWorkingDay(date) && isNotPublicHoliday(countryCode, date);
    }

    private boolean isWorkingDay(LocalDate date) {
        return workingDays[date.getDayOfWeek() - 1];
    }

    private boolean isNotPublicHoliday(String countryCode, LocalDate date) {
        return publicHolidayRepository.find(countryCode, date) == null;
    }
}
